require_relative "../Expr"

# Expression for binary operators. An expression 10(2) is also a binary operator.
# Its operator will be `:PAREN_O`
#
# @author Paul T.
class Calcula::Exprs::BinopExpr < Calcula::Expr

  # @param op [Calcula::Token] Should have type prefixed with `OP_`
  # @param left [Calcula::Expr]
  # @param right [Calcula::Expr]
  def initialize(op, left, right)
    @op = op
    @left = left
    @right = right
  end

  # @see Calcula::Expr#to_s
  # @param (see Calcula::Expr#to_s)
  # @return (see Calcula::Expr#to_s)
  def to_s(form: :src)
    leftTxt = @left.to_s(form: form)
    rightTxt = @right.to_s(form: form)
    case form
    when :src, :ruby then
      case @op.id
      when :PAREN_O then
        "#{leftTxt}#{"." if form == :ruby}(#{rightTxt})"
      when :OP_EQ then
        "#{leftTxt}#{form == :ruby ? "==" : "="}#{rightTxt}"
      when :AND then
        "#{leftTxt}#{form == :ruby ? "&&" : " and "}#{rightTxt}"
      when :OR then
        "#{leftTxt}#{form == :ruby ? "||" : " or "}#{rightTxt}"
      when :COMPOSE then
        "->(*x){#{leftTxt}.(#{rightTxt}.(*x))}"
      else
        "#{leftTxt}#{@op.text}#{rightTxt}"
      end
    when :tree then
      "(#{@op.text} #{leftTxt} #{rightTxt})"
    else
      nil
    end
  end

  # @see Calcula::Expr#children
  # @param (see Calcula::Expr#children)
  # @return (see Calcula::Expr#children)
  def children
    [@left, @right]
  end
end
